package com.ruoyi.store.service.impl;

import com.ruoyi.activiti.api.RemoteActivitiService;
import com.ruoyi.basedata.api.RemoteGoodsService;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.finance.api.RemoteBuyMustPayService;
import com.ruoyi.finance.domain.BuyMustPay;
import com.ruoyi.store.api.RemoteWarehouseGoodsService;
import com.ruoyi.store.mapper.StockInDetailMapper;
import com.ruoyi.store.mapper.StockInMapper;
import com.ruoyi.store.mapper.WarehouseGoodsMapper;
import com.ruoyi.store.service.IStockInService;
import com.ruoyi.store.service.IStockLossService;
import com.ruoyi.store.service.buy.BuyMustPayService;
import com.ruoyi.system.api.domain.basedata.Goods;
import com.ruoyi.system.api.domain.store.*;
import com.ruoyi.system.api.dto.ActApprovalDTO;
import com.ruoyi.system.api.dto.StockInDTO;
import com.ruoyi.xiaoshou.api.RemoteSaleBackService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.ruoyi.common.core.utils.PageUtils.startPage;

/**
 * 入库记录Service业务层处理
 *
 * @author lmj
 * @date 2024-10-31
 */
@Service
@Slf4j
@Transactional
public class StockInServiceImpl implements IStockInService {
    @Autowired
    private StockInMapper stockInMapper;
    @Autowired
    private StockInDetailMapper stockInDetailMapper;
    @Autowired
    private WarehouseGoodsMapper warehouseGoodsMapper;
    @Autowired
    private RemoteSaleBackService remoteSaleBackService;
    @Autowired
    private IStockLossService stockLossService;

    @Autowired
    private BuyMustPayService buyMustPayService;
    @Autowired
    private RemoteBuyMustPayService remoteBuyMustPayService;
    @Autowired
    private RemoteActivitiService remoteActivitiService;

    @Autowired
    private RemoteGoodsService remoteGoodsService;
    @Autowired
    private RemoteWarehouseGoodsService remoteWarehouseGoodsService;

    /**
     * 查询入库记录
     *
     * @param id 入库记录主键
     * @return 入库记录
     */
    @Override
    public StockIn selectStockInById(Integer id) {
        return stockInMapper.selectStockInById(id);
    }

    @Override
    public StockIn selectStockInByCode(String code) {
        log.info("selectStockInByCode params:{}", code);
        StockIn stockIn = stockInMapper.getStockInByCode(code);
        return stockIn;
    }

    public List<StockIn> selectStockInListForBuyBack(StockInDTO stockInDTO) {
        startPage();
        return stockInMapper.selectStockInListForBuyBack(stockInDTO);
    }

    /**
     * 查询入库记录列表
     *
     * @param stockIn 入库记录
     * @return 入库记录
     */
    @Override
    public List<StockIn> selectStockInList(StockIn stockIn) {
        return stockInMapper.selectStockInList(stockIn);
    }

    /**
     * 新增入库记录
     *
     * @param stockIn 入库记录
     * @return 结果
     */
    @Override
    public AjaxResult insertStockIn(StockIn stockIn) {
        log.info("StockInServiceImpl insertStockIn params:{}", stockIn);
        List<StockInDetail> stockInDetails = stockIn.getStockInDetails();
        //判断编号不能重复
        int count = stockInMapper.getStockInCount(stockIn);
        if (count > 0) {
            log.error("insertStockIn stockInCode repeat");
            return AjaxResult.warn("入库单编号重复，请修改");
        }
        boolean flag = stockInMapper.insertStockIn(stockIn) > 0;
        if (!flag) {
            log.error("insertStockIn fail");
            throw new RuntimeException("插入入库单错误");
        }
        //获取入库单id
        int stockInId = stockInMapper.getStockInByCode(stockIn.getStockInCode()).getId();
        for (StockInDetail stockInDetail : stockInDetails) {
            stockInDetail.setStockInId(stockInId);
        }
        for (StockInDetail stockInDetail : stockInDetails) {
            boolean flag1 = stockInDetailMapper.insertStockInDetail(stockInDetail) > 0;
            if (!flag1) {
                log.error("insertStockInDetail fail");
                throw new RuntimeException("插入入库单详情错误");
            }
        }
        //添加审核
        //采购退货申请添加审核任务
        ActApprovalDTO actApprovalDTO = new ActApprovalDTO();
        actApprovalDTO.setProcessDefinitionKey("stockIn");
        actApprovalDTO.setOrderCode(stockIn.getStockInCode());
        actApprovalDTO.setTaskName(stockIn.getStockInCode() + "入库申请");
        actApprovalDTO.setDeptId(103);
        AjaxResult addApprovalAjaxResult = remoteActivitiService.addApproval(actApprovalDTO);
        Integer code = (Integer) addApprovalAjaxResult.get("code");
        if (code != 200) {
            throw new RuntimeException("新增失败");
        }
        return AjaxResult.success();
    }

    @Override
    public AjaxResult confirmIn(StockIn stockIn1) {
        log.info("StockInServiceImpl confirmIn params:{}", stockIn1);
        //根据编号获取入库单
        StockIn stockIn = stockInMapper.getStockInByCode(stockIn1.getStockInCode());
        StockInDetail stockInDetail = new StockInDetail();
        stockInDetail.setStockInId(stockIn.getId());
        List<StockInDetail> stockInDetails = stockInDetailMapper.selectStockInDetailList(stockInDetail);
        if (!(stockInDetails.size() > 0)) {
            return AjaxResult.warn("该入库单没有入库详情！");
        }
        //生成报损单
        StockLoss stockLoss = new StockLoss();
        stockLoss.setOrderCode("BS-" + DateUtils.dateTimeNow());
        stockLoss.setOrderDate(new Date());
        stockLoss.setLossType(stockIn.getInventoryType() == 1 ? 0 : stockIn.getInventoryType() == 4 ? 1 : 2);
        stockLoss.setSrcOrderCode(stockIn.getStockInCode());
        List<StockLossDetail> stockLossDetailList = new ArrayList<>();
        for (StockInDetail stockInDetail1 : stockInDetails) {
            if (stockInDetail1.getNoPassNum() > 0) {
                StockLossDetail stockLossDetail = new StockLossDetail();
                //报损详情仓库
                stockLossDetail.setHouseId(stockInDetail1.getHouseId());
                stockLossDetail.setGoodsId(stockInDetail1.getGoodsId());
                stockLossDetail.setPrice(stockInDetail1.getCost());
                stockLossDetail.setTotal(stockInDetail1.getNoPassNum());
                stockLossDetailList.add(stockLossDetail);
            }
        }
        if (stockLossDetailList.size() > 0) {
            stockLoss.setStockLossDetailList(stockLossDetailList);
            AjaxResult ajaxResult = stockLossService.insertStockLoss(stockLoss);
            if (!ajaxResult.isSuccess()) {
                log.error("insertStockLoss fail");
                throw new RuntimeException("确认入库失败");
            }
        }
        //遍历details，查看对应的仓库有没有对应的商品，有就加数量，没有就在仓库中添加商品，最后更新入库单的状态
        for (StockInDetail stockInDetail1 : stockInDetails) {


            WarehouseGoods warehouseGoods = new WarehouseGoods();
            Assert.notNull(stockInDetail1.getGoodsId(), "不存在商品");
            Assert.notNull(stockInDetail1.getHouseId(), "不存在仓库");
            warehouseGoods.setGoodsId(stockInDetail1.getGoodsId());
            warehouseGoods.setHouseId(stockInDetail1.getHouseId());
            WarehouseGoods warehouseGoods1 = warehouseGoodsMapper.selectWarehouseGoodsByGoodsIdAndHouseId(warehouseGoods);
            if (warehouseGoods1 != null) {
                warehouseGoods1.setStock(warehouseGoods1.getStock() + stockInDetail1.getNum());
                warehouseGoods1.setModifyBy(SecurityUtils.getUsername());
                warehouseGoods1.setModifyDate(new Date());
                boolean flag = warehouseGoodsMapper.updateWarehouseGoods(warehouseGoods1) > 0;
                if (!flag) {
                    log.error("StockInServiceImpl updateWarehouseGoods fail");
                    throw new RuntimeException("更新库存失败！");
                }
            } else {
                warehouseGoods.setStock(stockInDetail1.getNum());
                warehouseGoods.setCreateBy(SecurityUtils.getUsername());
                warehouseGoods.setCreateDate(new Date());
                boolean flag = warehouseGoodsMapper.insertWarehouseGoods(warehouseGoods) > 0;
                if (!flag) {
                    log.error("StockInServiceImpl insertWarehouseGoods fail");
                    throw new RuntimeException("插入库存失败！");
                }
            }

            //修改商品成本
            if (stockIn1.getInventoryType() == 1) {
                //获取商品信息，库存数量
                Goods goods = remoteGoodsService.getGoodsById(stockInDetail1.getGoodsId()).getData();
                int stockNum = warehouseGoodsMapper.selectStockByGoodsId(stockInDetail1.getGoodsId());
                BigDecimal costAll = stockInDetail1.getCost().multiply(BigDecimal.valueOf(stockInDetail1.getNum())).add(goods.getCost().multiply(BigDecimal.valueOf(stockNum)));
                BigDecimal cost = (costAll).divide(BigDecimal.valueOf(stockNum), 2, RoundingMode.HALF_UP);
                goods.setCost(cost);
                remoteGoodsService.edit(goods);
            }

        }
        stockIn.setModifyBy(SecurityUtils.getUsername());
        stockIn.setModifyDate(new Date());
        stockIn.setStatus(1);
        boolean flag2 = stockInMapper.updateStockIn(stockIn) > 0;
        if (!flag2) {
            log.error("StockInServiceImpl updateStockIn fail");
            throw new RuntimeException("更新入库单失败！");
        }
        //更新入库状态
        //销售退货单
        if (stockIn.getInventoryType() == 4) {
            //将入库的数量和不合格的数量和需要付款的金额传给退货单
            R<String> stringR = remoteSaleBackService.refreshStatus(stockIn);
            if (!"200".equals(stringR.getData())) {
                log.error("StockInServiceImpl refreshStatus fail");
                throw new RuntimeException("更新销售退货单状态失败");
            }
            //生成应付单
            BuyMustPay buyMustPay = new BuyMustPay();
            buyMustPay.setCode("XSTHYF-" + System.currentTimeMillis());
            buyMustPay.setSourceCode(stockIn.getStockInCode());
            buyMustPay.setDocTime(new Date());
            buyMustPay.setTotalAmount(stockIn.getPassCost());
            buyMustPay.setVerifiedAmount(BigDecimal.ZERO);
            buyMustPay.setCreateBy(SecurityUtils.getUsername());
            buyMustPay.setCreateTime(new Date());
            R<Boolean> result = remoteBuyMustPayService.addBuyMustPay(buyMustPay, SecurityConstants.INNER);
            if (!result.getData()) {
                log.error("addBuyMustPay fail");
                throw new RuntimeException("添加收款单失败");
            }
        }
        //添加采购应付单和更新采购订单入库状态
        if (stockIn.getInventoryType() == 1) {

            buyMustPayService.addBuyMustPayByStockIn(stockIn);
        }
        return AjaxResult.success("入库成功！");
    }

    /**
     * 修改入库记录
     *
     * @param stockIn 入库记录
     * @return 结果
     */
    @Override
    public AjaxResult updateStockIn(StockIn stockIn) {
        log.info("StockInServiceImpl updateStockIn params:{}", stockIn);
        List<StockInDetail> stockInDetails = stockIn.getStockInDetails();
        //删除详情
        StockIn stockIn1 = stockInMapper.selectStockInById(stockIn.getId());
        int stockInId = stockIn1.getId();
        boolean flag = stockInDetailMapper.deleteStockInDetailByStockInId(stockInId) > 0;
        if (!flag) {
            log.error("updateStockIn deleteStockInDetailByStockInId error");
            throw new RuntimeException("删除入库详情错误");
        }
        //判断编号不能重复
        int count = stockInMapper.getStockInCount(stockIn);
        if (count > 0) {
            log.error("updateStockIn stockInCode repeat");
            return AjaxResult.warn("入库单编号重复，请修改");
        }
        boolean flag1 = stockInMapper.updateStockIn(stockIn) > 0;
        if (!flag1) {
            log.error("updateStockIn fail");
            throw new RuntimeException("修改入库单错误");
        }
        for (StockInDetail stockInDetail : stockInDetails) {
            boolean flag2 = stockInDetailMapper.insertStockInDetail(stockInDetail) > 0;
            if (!flag2) {
                log.error("updateStockIn insertStockInDetail fail");
                throw new RuntimeException("修改入库单详情错误");
            }
        }
        return AjaxResult.success();
    }

    @Override
    public int innerUpd(StockIn stockIn) {
        return stockInMapper.updateStockIn(stockIn);
    }

    /**
     * 批量删除入库记录
     *
     * @param ids 需要删除的入库记录主键
     * @return 结果
     */
    @Override
    public AjaxResult deleteStockInByIds(Integer[] ids) {
        log.info("StockInServiceImpl deleteStockInByIds params:{}", (Object) ids);
        //先把id对应的订单编号查询出来，然后把对应的详情删除
        for (int id : ids) {
            StockIn stockIn = stockInMapper.selectStockInById(id);
            int stockInId = stockIn.getId();
            StockInDetail stockInDetail = new StockInDetail();
            stockInDetail.setStockInId(stockInId);
            boolean flag = stockInDetailMapper.deleteStockInDetail(stockInDetail) > 0;
            if (!flag) {
                log.error("deleteStockInByIds deleteStockInDetail fail");
                throw new RuntimeException("删除入库单详情失败");
            }
            boolean flag1 = stockInMapper.deleteStockInById(id) > 0;
            if (!flag1) {
                log.error("deleteStockInByIds deleteStockInById fail");
                throw new RuntimeException("删除入库单失败");
            }
        }
        return AjaxResult.success();
    }

    /**
     * 删除入库记录信息
     *
     * @param id 入库记录主键
     * @return 结果
     */
    @Override
    public int deleteStockInById(Integer id) {
        return stockInMapper.deleteStockInById(id);
    }

    @Override
    public List<StockIn> getStockList(StockIn stockIn) {
        log.info("StockInServiceImpl getStockList params:{}", stockIn);
        List<StockIn> stockIns = stockInMapper.selectStockInList(stockIn);
        return stockIns;
    }


    @Override
    public List<StockIn> selectStockInListPlus(StockInDTO stockInDTO) {
        return stockInMapper.selectStockInListPlus(stockInDTO);
    }

    @Override
    public List<StockIn> getUsePayList(StockInDTO stockInDTO) {
        return stockInMapper.getUsePayList(stockInDTO);
    }

    @Override
    public List<StockInDTO> selectStockInListByCodeList(List<String> codeList) {
        Assert.notEmpty(codeList, "编号列表为空");
        return stockInMapper.selectStockInListByCodeList(codeList);
    }

    @Transactional
    @Override
    public int verified(String code, BigDecimal paidAmount) {
        StockIn stockIn = stockInMapper.getStockInByCode(code);
        Assert.notNull(stockIn, "入库单不存在");
        if (paidAmount.compareTo(stockIn.getCost().subtract(stockIn.getPaidAmount() == null ? BigDecimal.ZERO : stockIn.getPaidAmount())) > 0) {
            throw new ServiceException("结算金额大于未结算金额");
        }
        stockIn.setPaidAmount(stockIn.getPaidAmount().add(paidAmount));
        return stockInMapper.updateStockIn(stockIn);
    }
}
